<?php
/**
* EChainableBehavior class file.
*
* @author Vitaliy Stepanenko <mail@vitaliy.in>, http://nayjest.ru
* @license BSD
* @version 1.1
*/

/**
*  Pass this constant as last parameter if you need to return result of method
*  If you need to get value of property just call method with corresponding name and without parameters 
*/
defined('ECB_RETURN') or define('ECB_RETURN',3073036554775807);

/**
* EChainableBehavior gives posibility to use jQuery-like chainable style of working with public component properties, class methods that not return important data or AR attributes
* example:
* $user->attachBehavior('chain',array('class'=>'ext.behaviors.chainable.EChainableBehavior'));
* $id = $user->chain       
*       ->email('mail@example.com') # set $user->email
*       ->firstName('Ivan')         # set $user->firstName
*       ->lastName('Ivanov')
*       ->id();  
* 
* It's convenient to use with clientScript to make code of views more clean:
* $res=Yii::app()->clientScript->chain
*       ->registerScriptFile('script1.js')
*       ->registerScriptFile('script2.js')
*       ->registerScriptFile('script3.js')
*       ->coreScriptUrl(); //will return clientScript->coreScriptUrl
* 
* Before using of chainable behavior you need to configure this component in your application configuration:
* 'components'=>array(
*   'clientScript'=>array(   
*           'behaviors'=>array(
*               'chain'=>'ext.behaviors.chainable.EChainableBehavior'
*           )
*    ),
* ....
* ),
* 
* 
* If last parameter passed to method is equal to constant ECB_RETURN then method result will returned instead of $this 
*/
class EChainableBehavior extends CBehavior  {    

    public function __call($name, $params=null) {
        $o=$this->getOwner();
        
        if (method_exists($o,$name)){
            $returnMethodValue=false;
            $argsCount=func_num_args();

            if ($argsCount>1)
            {
                $argsList = func_get_args();
                unset($argsList[0]);#unset method name

                #if we need to return value, remove ECB_RETURN from method arguments & set $returnMethodValue
                if ($argList[$argsCount-1]==ECB_RETURN)
                {
                    unset($argsList[$argsCount-1]);
                    $returnMethodValue=true;
                }

            }else{
                $argList=array();
            }

            $result=call_user_func_array(array($o,$name),$params);

            if ($returnMethodValue){
                return $result;
            }else{
                return $this;
            }

        }else{#if not method
            # Get value        
            if (!$params){
                if (isset($o->$name)){                
                    return $o->$name;                              
                }elseif (method_exists($o,'getAttribute')){    
                    return $o->getAttribute($name);
                }    
            #Set value
            }else{
                if (isset($o->$name))
                {
                    $o->$name=$params[0];
                    return $this;
                }elseif (method_exists($o,'setAttribute'))    
                    if ($o->setAttribute($name,$params[0])){
                        return $this;
                    }else{
                        return false;           
                }    
            }       
        }#not method
    }#function
}


